-
-
Notifications
You must be signed in to change notification settings - Fork 31k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-29757: don't swallows errors in the socket.create_connection()
utility loop
#562
Conversation
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA). Unfortunately we couldn't find an account corresponding to your GitHub username on bugs.python.org (b.p.o) to verify you have signed the CLA. This is necessary for legal reasons before we can look at your contribution. Please follow these steps to help rectify the issue:
Thanks again to your contribution and we look forward to looking at it! |
@ankostis, thanks for your PR! By analyzing the history of the files in this pull request, we identified @freddrake, @ethanfurman, @asvetlov, @giampaolo and @cf-natali to be potential reviewers. |
Could you open an issue to discuss this, @ankostis ? We prefer to discuss design and such on bugs.python.org so that GitHub is only used for code review. |
By the way my CLA has been signed. |
socket.create_connection()
utility loopsocket.create_connection()
utility loop
Thanks. And just in case you didn't notice, Travis failed (not sure if it's because of the PR changes). |
Thanks, I will look at it tomorrow. |
@ankostis you can also wait for any discussion to be had about the issue before you put in more time in case this isn't accepted for some reason. |
@brettcannon grateful for your care to contributors like me. Anyhow, I did some changes on the OP regarding what I tried to implement and what I consider as possible solutions & open questions. |
Lib/socket.py
Outdated
@@ -714,12 +714,12 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, | |||
return sock | |||
|
|||
except error as _: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use _
, it would look much better with a normal variable name such as e
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use one letter name like "e" :-) Use "error", "exc" or whatever else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in ec887c0c3 (rebased on latest master).
Had to rewrite again (b39d4b1) to rename e
--> ex
(i like it also this way, just trying to preserve styles).
Lib/socket.py
Outdated
@@ -700,7 +700,7 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, | |||
""" | |||
|
|||
host, port = address | |||
err = None | |||
errs = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errs
-> errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in ec887c0c3 b39d4b1 (rebased on latest master).
I'll post some feedback to bpo. |
## Context The utility method `socket.create_connection()` currently works like that: 1. resolve the destination-address into one or more IP(v4 & v6) addresses; 2. loop on each IP address and stop to the 1st one to work; 3. if none works, re-raise the last error. ## The problem So currently the loop in `socket.create_connection()` ignores all intermediate errors and reports only the last connection failure, which might be irrelevant. For instance, when both IPv4 & IPv6 networks are supported, usually the last address is a IPv6 address and it frequently fails with an irrelevant error - the actual cause have already been ignored. ## Possible solutions & open questions To facilitate network debugging, there are at least 3 options: a. log each failure [as they happen](/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Lib/socket.py#L717), but that would get the final failure twice: once as a (warning?) message, and once as an exception . b. collect all failures and log them only when connection fails to collect the errors, but that might miss important infos to the user; c. collect and return all failures in list attached to the raised exception. A question for cases (a) & (b) is what logging "means" to use: the `warnings` or `logging` module? And if `logging` is chosen, log them in `'DEBUG'` or `'WARNING'` level? Case (c), implemented in this PR sidesteps the above questions.
Now all TCs pass, because I re-raise the exact original error in case only a single one was collected. But still, this PR is needs more work because of 2 issues: Abuse of
|
@the-knights-who-say-ni I have signed CLA; is there some problem with it? |
- Rename `_` and `errs` variable names. - Raise original error if a single one. - Improve a bit error message, but still no Errno provided for when multiple errors are included.
@ankostis I just checked the logs and it seems you didn't set your GitHub username on your bugs.python.org (i.e. the bot can't find any account on bugs.python.org that has the GitHub username "ankostis" set). Fix that and hopefully the bot will pick up that you signed the CLA. |
OK, my gh-username has been set. |
@ankostis that worked! |
Any ideas which road to take? And where should the discussion take place, here on on python-tracker? |
@ankostis code review issues are discussed here, all other discussions (such as what the best approach is, etc.) should happen on the issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that PEP 654 -- Exception Groups and except*
would be the best way to implement multiple exceptions here, but this will need to wait while being implemented. Or you could try the without except*
https://www.python.org/dev/peps/pep-0654/#programming-without-except
This PR is stale because it has been open for 30 days with no activity. |
Superseded by #91586 |
Context
The utility method
socket.create_connection()
currently works like that:The problem
So currently the loop in
socket.create_connection()
ignores all intermediate errors and reports only the last connection failure, which might be irrelevant. For instance, when both IPv4 & IPv6 networks are supported, usually the last address is a IPv6 address and it frequently fails with an irrelevant error - the actual cause have already been ignored.Possible solutions
To facilitate network debugging, there are at least 3 options:
a. log each failure as it happens, but that would get the final failure twice: once as a (warning?) message, and once as an exception .
b. collect all failures and log them only when connection fails, but that might miss important infos to the user;
c. collect and return all failures in list attached to the raised exception, which also might miss important infos.
open questions
Q1. A question for all cases is what logging "means" to use: the
warnings
orlogging
module?Q2. And if
logging
is chosen, log them in'DEBUG'
or'WARNING'
level?Q3. Finally, cases (b) & (c) need an answer whether to log collected errors in the case that connection passes.
The 1st part of case (c) is implemented in this PR.